C、CPP控制台程序、WindowsAPI程序、MFC程序理解与比较

在编程语言中,函数是一个很重要的概念,其身影无处不在。在面向过程的编程方式中,函数更是程序的基本构建模块,在面向对象的编程方式中,函数演变为类或对象的成员(当然也可以使用与类无关的函数)。

函数由函数头和函数体组成。函数头包括域属性(如external、static或类域)、返回值类型、函数名、及参数。域属性包括其在多文件编程中的可见范围,是否是属于某一个类的成员?返回值类型是指函数返回的值的具体数据类型(可以理解为函数输出的一部分)。函数名是函数保存在内存代码区的首地址,用于函数的调用及函数指针的右值。参数可以理解为函数的输入、输出(如果是引用或指针作为参数,可以理解为是一个种输出,因为其操作或更新的数据是引用或指针的地址值所指向的内存单元)。在C\C++中,函数体位于{}中,函数体是函数功能的具体实现。

如果用一台手机来理解函数概念,手机裸露在外的操作界面就像是函数头,外壳内的组件就像是函数体中,外壳就像是{}。

函数的开发者和使用者可以站在不同的角度去理解函数的构造,函数的开发者需要负责函数头作为界面(interface)的友好性及稳定性,以及保证实现(implement)函数功能的函数体的空间和时间效率。而函数的使用者可以不关心函数功能的具体实现(当然了解其具体实现能更好地加深对函数的理解),也就是不心关心函数体的具体内容,只需关心函数使用的具体细节,也就是函数体的内容。

就如同一台手机,手机开发者要负责手机从外部操作到内部零部件的全部,而手机购买者(使用者)则只需关心怎样使用即可。

一个数据集D,以及操作这个数据集D的代码集C如何更好地形成一个整体,在函数的概念中有一定的体现,也就是通过参数和局部变量形成数据集D,以及在函数体中包含一个函数指针,由其指向的函数代表代码集C。但这种封装性还是体现得不够充分。如果把数据集D,以及操作这个数据集D的代码集C全部归属(或限定)到某一个类别,并设定访问控制(access modifier)的概念,这种封装性就能得到最充分的体现,这种思想就是面向对象的类类型概念。访问控制就像一个手机外壳,用public修饰的类(对象)的属性(数据集D)或方法(代码集C)就是一个类(对象)提供的界面(interface),是公共的,公开的,裸露在外的,使用者密切关注的;而private修饰的类(对象)的属性(数据集D)或方法(代码集C)就是一个类(对象)提供的具体实现,是私密的,隐藏在内的,使用者可以不加以密切注意的。

于是,一些编程大牛对于一些使用频率很高的功能便开发出界面友好稳定、实现效率高的函数和类,保存在库(library)中,也就是函数库或类库,实现共享。一些优秀函数库或类库也就成了编程语言的有机组成部分。

一种计算机语言的应用程序是运行在某一操作系统之上的,某一操作系统对某一语言的支持是通过其某一语言的函数库或类库来实现的。

1 控件台程序

控制台程序程序只关心数据,不在乎界面,在一个简单的Shell中执行。

控制台程序用字符进行交互,不需要鼠标操作,也就是没有图形界面,也就是不需要使用控件做为输入、输出的媒介。

而window api与MFC主要使用控件(视窗)做为交互媒介,也就有了资源对象(不是类类型对象)的概念,同时也有了事件消息和消息响应函数的概念(Message Based,Event Driven)。

2 Windows API编程

当Windows操作系统开始占据主导地位的时候,开发Windows平台下的应用程序成为人们的需要。而在Windows程序设计领域处于发展的初期,Windows程序员所能使用的编程工具唯有API(Application Programming Interface)函数,这些函数是Windows提供给应用程序与操作系统的接口,他们犹如“积木块”一样,可以搭建出各种界面丰富,功能灵活的应用程序。所以可以认为API函数是构筑整个Windows框架的基石,在它的下面是Windows的操作系统核心,而它的上面则是所有的华丽的Windows应用程序。

Windows API所提供的功能可以归为七类:

2.1 基础服务(Base Services),提供对Windows系统可用的基础资源的访问接口。比如像:文件系统(file system)、外部设备(device)、进程(process)、线程(thread)以及访问注册表(Windows registry)和错误处理机制(error handling)。这些功能接口位于Windows下的 kernel32.dll和advapi32.dll中。

2.2 图形设备接口(GDI),提供功能为:输出图形内容到显示器、打印机以及其他外部输出设备。位于Windows下的gdi32.dll。

2.3 图形化用户界面(GUI),提供的功能有创建和管理屏幕和大多数基本控件(control),比如按钮和滚动条,接收鼠标和键盘输入,以及其他与GUI有关的功能。这些调用接口位于Windows下的user32.dll。从Windows XP版本之后,基本控件和通用对话框控件(Common Control Library)的调用接口放在comctl32.dll中。

2.4 通用对话框链接库(Common Dialog Box Library),为应用程序提供标准对话框,比如打开/保存文档对话框、颜色对话框和字体对话框等等。这个链接库位于Windows下comdlg32.dll中。它被归类为User Interface API之下。

2.5 通用控件链接库(Common Control Library),为应用程序提供接口来访问操作系统提供的一些高级控件。比如状态栏(status bar)、进度条(progress bars)、工具栏(toolbar)和标签(tab)等。这个链接库位于Windows下comctl32.dll中。它被归类为User Interface API之下。

2.6 Windows外壳(Windows Shell),作为Windows API的组成部分,不仅允许应用程序访问Windows外壳提供的功能,还对之有所改进和增强。它位于Windows下的shell32.dll中(Windows 95则在 shlwapi.dll中)。 它被归类为User Interface API之下。

2.7 网络服务(Network Services),为访问操作系统提供的多种网络功能提供接口。它包括NetBIOS、Winsock、NetDDE及RPC等。

3 从API到可视化编程

程序员想编写具有Windows风格的软件,必须借助API,API也因此被赋予至高无上的地位。但是,如若没有合适的Windows编程平台,那么Windows开发是一项很复杂的工作。在可视化编程IDE出来之前,那时的Windows程序开发还是比较复杂的工作,程序员必须熟记一大堆常用的API函数,而且还得对Windows操作系统有深入的了解。然而随着软件技术的不断发展,在Windows平台上出现了很多优秀的可视化编程环境,程序员可以采用“所见即所得”的编程方式来开发具有精美用户界面和功能强大的应用程序。

这些优秀可视化编程环境操作简单、界面友好(诸如VB、VC++、DELPHI等),在这些工具中提供了大量的类库和各种控件,它们替代了API的神秘功能,事实上这些类库和控件都是构架在WIN32 API函数基础之上的,是封装了的API函数的集合。它们把常用的API函数的组合在一起成为一个控件或类库,并赋予其方便的使用方法,所以极大的加速了Windows应用程序开发的过程。有了这些控件和类库,程序员便可以把主要精力放在程序整体功能的设计上,而不必过于关注技术细节。

4 API编程适应场合

实际上如果我们要开发出更灵活、更实用、更具效率的应用程序,必然要涉及到直接使用API函数,虽然类库和控件使应用程序的开发简单的多,但它们只提供Windows的一般功能,对于比较复杂和特殊的功能来说,使用类库和控件是非常难以实现的,这时就需要采用API函数来实现。

这也是API函数使用的场合,所以我们对待API函数不必刻意去研究每一个函数的用法,那也是不现实的(能用得到的API函数有几千个呢)。正如某位大虾所说:API不要去学,在需要的时候去查API帮助就足够了。但是,许多API函数令人难以理解,易于误用,还会导致出错,这一切都阻碍了它的推广。

5 从API到MFC

数以千计的Windows APIs,每个看起来都好象比重相若(至少你从手册上看不出来孰轻孰重)。有些APIs 彼此虽有群组关系,却没有相近或组织化的函数名称。星罗棋布,雾列星驰;又似雪球一般愈滚愈多,愈滚愈大。撰写Windows 应用程序需要大量的耐力与毅力,以及大量的小心谨慎!

MFC 帮助我们把这些浩繁的APIs,利用对象导向的原理,逻辑地组织起来,使它们具备抽象化、封装化、继承性、多态性、模块化的性质。

1989 年微软公司成立Application Framework 技术团队,名为AFX 小组,用以开发C++对象导向工具给Windows 应用程序开发人员使用。AFX 的"X" 其实没有什么意义,只是为了凑成一个响亮好念的名字。

这个小组最初的「宪章」,根据记载,是要"utilize the latest in object oriented technology toprovide tools and libraries for developers writing the most advanced GUI applications on themarket",其中并未画地自限与Windows 操作系统有关。果然,其第一个原型产品,有自己的窗口系统、自己的绘图系统、自己的对象数据库、乃至于自己的内存管理系统。当小组成员以此产品开发应用程序,他们发现实在是太复杂,又悖离公司的主流系统--Windows -- 太遥远。于是他们修改宪章变成"deliver the power of object-oriented solutionsto programmers to enable them to build world-class Windows based applications in C++." 这差不多正是Windows 3.0 异军崛起的时候。

C++ 是一个复杂的语言,AFX 小组预期MFC 的使用者不可能人人皆为C++ 专家,所以他们并没有采用所有的C++ 高阶性质(例如多重继承)。许多「麻烦」但「几乎一成不变」的Windows 程序动作都被隐藏在MFC 类别之中,例如WinMain 、RegisterClass、Window Procedure 等等等。

为了让MFC 尽可能地小,尽可能地快,AFX 小组不得不舍弃高度的抽象(导至过多的虚拟函数),而引进他们自己发明的机制,尝试在对象导向领域中解决Windows 消息的处理问题。这也就是Message Mapping 和Message routing 机制。注意,他们并没有改变C++ 语言本身,也没有扩大语言的功能。他们只是设计了一些令人拍案叫绝的宏,而这些宏背后隐藏着巨大的机制。

微软公司于1992/04 推出C/C++ 7.0 产品时初次向世人介绍了MFC 1.0,这个初试啼声的产品包含了20,000 行C++ 源代码,60 个以上的Windows 相关类别,以及其它的一般类别如时间、数据处理、文件、内存、诊断、字符串等等等。它所提供的,其实是一个"thin and efficient C++ transformation of the Windows API"。其32 位版亦在1992/07 随着Win32 SDK 推出。

MFC实现了控件的可视化,其application Wizard和class wizard可以实现程序和代码模块框架的自动化实现。

图片描述(最多50字)

开发需要读写文件的应用程序并且有简单的输入和输出可以利用单文档视结构。

开发注重交互的简单应用程序可以使用对话框为基础的窗口,如果文件读写简单这可利用CFile进行。

在要求在多个文档间传递数据时使用多文档视结构。

图片描述(最多50字)

6 图形界面程序中的资源

资源在Windows API中使用一种特殊的结构体指针,句柄来引用。

Windows API开发之初C++还没有出现,所以windows提供的API函数使用的封装数据类型是结构体(不是类)。随着C++的诞生与普及,Windows API+C++就诞生了MFC,且资源控件开发实现了可视化,而封装数据类型也用类类型来实现。

图片描述(最多50字)

常用的资源:ICON、CURSOR、BITMAP、FONT、DIALOG、MENU、ACCELERATOR、STRING、VERSIONINFO、TOOLBAR。

图片描述(最多50字)

7 图形界面程序中的事件与消息

Windows API是编程者自己把消息和响应函数联系在一起。mfc是编程者采用微软为我们做好了MESSAGE-MAP机制,来处理消息。

8 函数库和类库

Windows API和MFC都使用 .lib 文件。

.lib 分两种, 一种是 .lib 文件里面包含了 cpp 编译出来的代码, 链接的时候把需要的代码拷贝到 exe 里面,mfc,、crt在选择静态的时候使用这种方式。

另外一种是.lib中不包含代码, 只是描述该到哪个dll里面怎么找对应的代码. 这种编译出来的exe就需要dll一起才能运行。mfc、crt使用共享库的时候, 以及 Windows API 就是使用的这种方式。

API 的 dll 在 windows 系统的 system32 目录下, 图形界面相关的 API 在 USER32.dll 里,进程、文件之类的操作在 kernel32.dll 里。MSDN 的每个函数都会说明它在哪个头文件, 哪个 lib, 哪个 dll 里的。

9 C、C++控制台程序、Windows API程序、MFC程序比较

图片描述(最多50字)

C++ 并不是纯种的对象导向语言(SmallTalk 和Java 才是)。所以,MFC之中得以存在有不属于任何类别的全域函数,它们统统在函数名称开头冠以Afx。

SDK 程序只要包含WINDOWS.H 就好,所有API 的函数声明、消息定义、常数定义、宏定义、都在WINDOWS.H 档中。除非程序另调用了操作系统提供的新模块(如CommDlg、ToolHelp、DDEML...),才需要再各别包含对应的.H 档。

图片描述(最多50字)

关于类的继承性在MFC的控件类中有最充分的体现,在MFC中,控件类的框架都已搭建好,其中包含了最通用的属性和方法以及一些虚函数,开发者可以重写虚函数或派生控件类来实现自己的功能或个性化的需求。

-End-

本页共64段,6228个字符,14454 Byte(字节)